name: GitHub Workflow Related Checks

# Any change in triggers needs to be reflected in the concurrency group.
on:
  pull_request: {}
  push:
    branches:
      - main
      - ft/main/**

permissions: read-all

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.after }}
  cancel-in-progress: true

jobs:
  ginkgo-workflow-comments:
    name: Lint Ginko Workflows Comments
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          # hard-code the path instead of using ${{ github.repository }} to make sure it works for forked repo as well
          path: src/github.com/cilium/cilium

      # Load Ginkgo build from GitHub
      - name: Load ginkgo linter from GH cache
        uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
        id: cache
        with:
          path: /tmp/.ginkgo-build/
          key: ${{ runner.os }}-ginkgo-linter-${{ hashFiles('src/github.com/cilium/cilium/**/*.go') }}

      - name: Install Go
        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          # renovate: datasource=golang-version depName=go
          go-version: 1.22.0

      - name: Build Ginkgo
        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
        shell: bash
        run: |
          cd src/github.com/cilium/cilium
          go install github.com/onsi/ginkgo/ginkgo@v1.16.5
          mkdir -p /tmp/.ginkgo-build

      - name: Building Ginkgo Linter Test
        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
        shell: bash
        run: |
          cd src/github.com/cilium/cilium
          git apply contrib/testing/ginkgo-get-all-test-names.patch

          cd test
          /home/runner/go/bin/ginkgo build
          strip test.test
          tar -cz test.test -f test.tgz

      - name: Store Ginkgo Linter Test in GitHub cache path
        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
        shell: bash
        run: |
          cd src/github.com/cilium/cilium
          mkdir -p /tmp/.ginkgo-build/
          if [ -f test/test.tgz ]; then
            cp test/test.tgz /tmp/.ginkgo-build/
            echo "file copied"
          fi

      - name: Copy Ginkgo binary
        if: ${{ steps.cache.outputs.cache-hit == 'true' }}
        shell: bash
        run: |
          cd src/github.com/cilium/cilium/test/
          tar -xf /tmp/.ginkgo-build/test.tgz

      - name: Reading Comments From Workflows
        shell: bash
        run: |
          cd src/github.com/cilium/cilium

          grep '# K8s' .github/actions/ginkgo/main-focus.yaml | \
          sed -e 's/^[[:space:]]\+# //g' | \
          sort -u > /tmp/ginkgo-workflow-comments.txt

          grep '# Runtime' .github/workflows/conformance-runtime.yaml | \
          sed -e 's/^[[:space:]]\+# //g' | \
          sort -u > /tmp/runtime-workflow-comments.txt

      - name: Getting test runs output
        shell: bash
        run: |
          cd src/github.com/cilium/cilium/test

          ./test.test -ginkgo.failFast -ginkgo.dryRun -- --cilium.testScope=K8s | \
          grep TestRun | \
          grep -v 'TestRun\[Top Level\] Runtime' | \
          sed 's/TestRun\[Top Level\]\ //g' | \
          sort -u > /tmp/ginkgo-tests.txt

          ./test.test -ginkgo.failFast -ginkgo.dryRun -- --cilium.testScope=Runtime | \
          grep TestRun | \
          grep -v 'TestRun\[Top Level\] K8s' | \
          sed 's/TestRun\[Top Level\]\ //g' | \
          sort -u > /tmp/runtime-tests.txt

      - name: Checking diff Ginkgo Workflow
        shell: bash
        run: |
          diff /tmp/ginkgo-workflow-comments.txt /tmp/ginkgo-tests.txt --suppress-common-lines

          if [ $? -ne 0 ]; then
            echo ""
            echo "Ginkgo tests out of sync with comments from GH workflow:"
            echo "$diff"
            echo "Please fix the comments from .github/actions/ginkgo/main-focus.yaml accordingly"
            echo ""
            exit 1
          fi

      - name: Checking diff Runtime Workflow
        shell: bash
        run: |
          diff /tmp/runtime-workflow-comments.txt /tmp/runtime-tests.txt --suppress-common-lines

          if [ $? -ne 0 ]; then
            echo ""
            echo "Ginkgo tests out of sync with comments from GH workflow:"
            echo "$diff"
            echo ""
            echo "Please fix the comments from .github/workflows/conformance-runtime.yaml accordingly"
            exit 1
          fi

  ginkgo-schema-validation:
    name: Validate Ginko Schema
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
        with:
          python-version: '3.10'
      - name: Install yamela
        run: pip install yamale
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          # hard-code the path instead of using ${{ github.repository }} to make sure it works for forked repo as well
          path: src/github.com/cilium/cilium

      - name: Validate schema of ginkgo action files
        shell: bash
        run: |
          cd src/github.com/cilium/cilium/.github/actions/ginkgo/
          for type in focus k8s-versions prs scheduled; do
            yamale -s ${type}-schema.yaml *-${type}.yaml;
          done

  conformance-schema-validation:
    name: Validate k8s Versions Schema
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
        with:
          python-version: '3.10'
      - name: Install yamela
        run: pip install yamale
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          # hard-code the path instead of using ${{ github.repository }} to make sure it works for forked repo as well
          path: src/github.com/cilium/cilium

      - name: Validate schema of aws, azure and gke action files
        shell: bash
        run: |
          for dir in aws azure gke;do
            dir_base=".github/actions/${dir}"
            file_base="${dir_base}/k8s-versions"
            if [ -f ${file_base}.yaml ];then
              yamale -s ${file_base}-schema.yaml ${file_base}.yaml;
            fi
            if [ -f ${dir_base}/test-config-schema.yaml ];then
              yamale -s ${dir_base}/test-config-schema.yaml ${dir_base}/test-config-classic.yaml
              yamale -s ${dir_base}/test-config-schema.yaml ${dir_base}/test-config-helm.yaml
            fi
          done

  name-validation:
    name: Validate Workflow Names
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          # hard-code the path instead of using ${{ github.repository }} to make sure it works for forked repo as well
          path: src/github.com/cilium/cilium

      - name: Validate Job and Step names
        shell: bash
        run: |
          EXIT=0
          cd src/github.com/cilium/cilium/.github/workflows
          for FILE in *.yaml;do
            JOBS=$(yq '.jobs | to_entries | .[] | select(.value.name == null) | "  " + .key' $FILE)
            STEPS=$(yq '.jobs | to_entries | .[] as $job | $job.value.steps[] | {"key": $job.key, "name": .name} | select(.name == null) | "  "+.key' $FILE)
            if [ "${JOBS}" != "" ];then
              echo Jobs are missing name field, in file $FILE
              echo "${JOBS}" | awk '{for (i=1; i<=NF; i++) print "  " $i}'
              EXIT=1
            fi
            if [ "${STEPS}" != "" ];then
              echo Steps are missing name field, under these Jobs in file $FILE
              echo "${STEPS}" | awk '{for (i=1; i<=NF; i++) print "  " $i}'
              EXIT=1
            fi
          done
          exit ${EXIT}
